package com.meng.netty.handler;

import com.meng.netty.constant.PointOfSaleConstant;
import com.meng.model.PointOfSale;
import com.meng.netty.thread.WriteDataToRedisThread;
import com.meng.util.ThreadPoolUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;


/**
 * POS Server 处理类
 *
 * @author MENG
 * @version 2018/3/19
 * @see
 */
public class PointOfSaleHandler extends ChannelInboundHandlerAdapter
{
    Logger logger = LoggerFactory.getLogger(PointOfSaleHandler.class);
    /**
     * 从客户端收到新的数据时，这个方法会在收到消息时被调用
     *
     * @param ctx
     * @param msg
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws InterruptedException
    {
        PointOfSale pointOfSale = (PointOfSale)msg;

        ThreadPoolUtil.getWriteDataToRedisFixedThreadPool().submit(new WriteDataToRedisThread(pointOfSale));

        //回应客户端
        ctx.write(msg);
    }

    /**
     * 从客户端收到新的数据、读取完成时调用
     *
     * @param ctx
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx)
    {
       ctx.flush();
    }

    /**
     * 当出现 Throwable 对象才会被调用，即当 Netty 由于 IO 错误或者处理器在处理事件时抛出的异常时
     *
     * @param ctx
     * @param cause
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
    {
        logger.error("连接出现异常 : {}",cause.getMessage());

        cause.printStackTrace();

        ctx.close();
    }

    /**
     * 客户端与服务端第一次建立连接时 执行
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception
    {
        super.channelActive(ctx);

        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();

        String clientIp = insocket.getAddress().getHostAddress();

        logger.info("客户端IP : {} 已经建立连接...",clientIp);

    }

    /**
     * 客户端与服务端 断连时 执行
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception
    {
        super.channelInactive(ctx);

        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();

        String clientIp = insocket.getAddress().getHostAddress();

        logger.info("客户端IP : {} 已经断开连接...",clientIp);
    }

    /**
     * 服务端 当读超时时 会调用这个方法
     *
     * @param ctx
     * @param evt
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
        throws Exception
    {
        super.userEventTriggered(ctx, evt);

        logger.info("服务端 {}秒 没有收到数据了、自动断开连接",PointOfSaleConstant.READ_IDLE_TIME);

        ctx.close();
    }
}
